/**
  * @(#)Section.java 
  *
  * Represent a registration section for a course
  *
  * @author Course Scheduler Team
  *
  * @license GNU General Public License version 3 (GPLv3)
  *
  * This file is part of Course Scheduler, an open source, cross platform
  * course scheduling tool, configurable for most universities.
  *
  * Copyright (C) 2010-2012 Course Scheduler Team
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * 
  */
package com.pollicitus.scheduler.model;

import java.util.Collection;
import java.util.HashSet;

import com.pollicitus.scheduler.model.ClassLevel;
import com.pollicitus.scheduler.model.Course;
import com.pollicitus.scheduler.model.GradingMethod;
import com.pollicitus.scheduler.model.Instructor;
import com.pollicitus.scheduler.model.ScheduleType;
import com.pollicitus.scheduler.model.Section;
import com.pollicitus.scheduler.model.SectionMeeting;

/**
 * Represent a registration section for a course
 * 
 * @author Course Scheduler Team
 *
 */
public class Section {

	/**
	 * The most recent revision in which this file was changed in the source control system
	 */
	public static final String _revision = "$LastChangedRevision: 539 $";
	
	/**
	 * The date on which this file was last changed and submitted to source control
	 */
	public static final String _date = "$LastChangedDate: 2011-11-19 23:14:16 -0500 (Sat, 19 Nov 2011) $";
	
	/**
	 * The user which last changed the file and committed the change to source control
	 */
	public static final String _author = "$LastChangedBy: mike@pollicitus.com $";
	
	/**
	 * The URL which can be used to access this specific file within the source control system
	 */
	public static final String _headURL = "$HeadURL: https://courseschedulerx.googlecode.com/svn/trunk/course-scheduler/course-scheduler-core/src/main/java/com/pollicitus/scheduler/model/Section.java $";
	
	/**
	 * The source control file ID, comprised of the file name, latest revision, last changed date, and submitting user.
	 */
	public static final String _id = "$Id: Section.java 539 2011-11-20 04:14:16Z mike@pollicitus.com $";
		
	/**
	 * sectionID = the section identifier
	 * prof = the professor responsible for the section
	 * times = the list of times and places that the section meets
	 * availableSeats = the number of available availableSeats in a section
	 * format = the lecture format of the section
	 * parent = parent course
	 * crn = course registration number
	 * closed = if the course is not available for registration
	 * credits = number of credits the section is worth
	 */
	private String sectionID;
	private Instructor prof;
	private Collection<SectionMeeting> times;
	private int availableSeats;
	private int totalSeats;
	private ScheduleType format;
	private Course parent;
	private String crn;	
	private boolean closed;
	private int credits;	
	private GradingMethod grade;
	
	/**
	 * Default constructor which initializes the private variables 
	 */
	public Section() {
		super();
		times = new HashSet<SectionMeeting>();
	}
	
	/**
	 * Add a meeting time to this course section
	 * 
	 * @param meet the section meeting (meeting time) to add to the section
	 */
	public void addMeetingTime(SectionMeeting meet) {
		if(!this.times.contains(meet)) {
			this.times.add(meet);
		}else {
			//TODO what to do if meeting time already exists
			//probably ignore duplicates
		}
	}
	
	/**
	 * Add the list of meeting times to this course section
	 * 
	 * @param meetings an array of meetings to add to this section
	 */
	public void addMeetingTime(SectionMeeting[] meetings) {
		for(SectionMeeting meet: meetings) {
			addMeetingTime(meet);
		}
	}
	
	/**
	 * Return the section ID for this Section
	 * 
	 * @return the sectionID
	 */
	public String getSectionID() {
		return sectionID;
	}
	
	/**
	 * Set the Section's identifier
	 * 
	 * @param sectionID the sectionID to use
	 */
	public void setSectionID(String sectionID) {
		this.sectionID = sectionID;
	}
	
	/**
	 * Return the Instructor responsible for the section
	 * 
	 * @return the prof teaching the section
	 */
	public Instructor getProf() {
		return prof;
	}
	
	/**
	 * Set the Instructor responsible for the section
	 * 
	 * @param prof the prof to use
	 */
	public void setProf(Instructor prof) {
		this.prof = prof;
	}
	
	/**
	 * Return the days and times that the section meets 
	 * 
	 * @return the section meeting times
	 */
	public Collection<SectionMeeting> getTimes() {
		return times;
	}
	
	/**
	 * Set the list of meeting times
	 * 
	 * @param times the times to use
	 */
	public void setTimes(Collection<SectionMeeting> times) {
		this.times = times;
	}
	
	/**
	 * Return the number of open availableSeats
	 * 
	 * @return the available availableSeats
	 */
	public int getAvailableSeats() {
		return availableSeats;
	}
	
	/**
	 * Set the number of available seats
	 * 
	 * @param availableSeats the available seats to use
	 */
	public void setAvailableSeats(int seats) {
		this.availableSeats = seats;
	}
	
	/**
	 * Set the total number of seats
	 * 
	 * @return the total number of seats
	 */
	public int getTotalSeats(){
		return totalSeats;
	}
	
	/**
	 * Set the total number of seats
	 * 
	 * @param seats the total number of seats
	 */
	public void setTotalSeats(int seats){
		this.totalSeats = seats;
	}

	/**
	 * Return the section scheduling format
	 * 
	 * @return the format the section will use
	 */
	public ScheduleType getFormat() {
		return format;
	}

	/**
	 * Set the scheduling format the section will use
	 * 
	 * @param format the scheduling format to use
	 */
	public void setFormat(ScheduleType format) {
		this.format = format;
	}

	/**
	 * Return the parent course for this section
	 * 
	 * @return the parent course
	 */
	public Course getParent() {
		return parent;
	}

	/**
	 * Set the parent course for this section
	 * 
	 * @param parent the parent to use
	 */
	public void setParent(Course parent) {
		this.parent = parent;	
	}

	/**
	 * Return the course request number used when scheduling
	 * 
	 * @return the crn for the section
	 */
	public String getCrn() {
		return crn;
	}

	/**
	 * Set the course request number to be used when scheduling
	 * 
	 * @param crn the crn to use
	 */
	public void setCrn(String crn) {
		this.crn = crn;
	}

	/**
	 * Return if there are no more seats available
	 * 
	 * @return if the course is closed
	 */
	public boolean isClosed() {
		return closed;
	}

	/**
	 * Set if the course does not have any more available seats
	 * 
	 * @param closed if ther are no more seats
	 */
	public void setClosed(boolean closed) {
		this.closed = closed;
	}

	/**
	 * Return the number of credits the section is worth
	 * 
	 * @return the credits
	 */
	public int getCredits() {
		return credits;
	}

	/**
	 * Set the number of credits the section is worth
	 * 
	 * @param credits the credits to set
	 */
	public void setCredits(int credits) {
		this.credits = credits;
	}
	
	/**
	 * Return the parent course's course ID
	 * 
	 * @return the course ID
	 */
	public String getCourseID() {
		return parent.getCourseID();
	}

	/**
	 * Return the parent course's department
	 * 
	 * @return the course department
	 */
	public String getDepartment() {
		return parent.getDepartment();
	}

	/**
	 * Return the parent course's description
	 * 
	 * @return the course description
	 */
	public String getDescription() {
		return parent.getDescription();
	}

	/**
	 * Return the parent course's name
	 * 
	 * @return the course name
	 */
	public String getName() {
		return parent.getName();
	}

	/**
	 * Return the parent course's registration level
	 * 
	 * @return the registration level
	 */
	public ClassLevel getLevel() {
		return parent.getLevel();
	}

	/**
	 * Return the parent course's registration term
	 * 
	 * @return the registration term
	 */
	public String getTerm() {
		return parent.getTerm();
	}

	/**
	 * Return the owning university
	 * 
	 * @return the university
	 */
	public String getUniversity() {
		return parent.getUniversity();
	}

	/**
	 * Return the grading method which will be used for the section
	 * 
	 * @return the grade
	 */
	public GradingMethod getGrade() {
		return grade;
	}
	
	/**
	 * Set the section's grading method
	 * 
	 * @param grade the grade to set
	 */
	public void setGrade(GradingMethod grade) {
		this.grade = grade;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object other){
		Section section = (Section)other;
		
		//compare based on the parent course equality and the section identifier
		return section.getParent().equals(this.getParent()) && 
				section.getSectionID().compareTo(this.getSectionID()) == 0;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode(){
		//use the same fields that define equality for the hashcode
		return this.getParent().hashCode() ^ this.getSectionID().hashCode();
	}
}
